package com.lfy.utils;

import com.lfy.domain.entity.JobDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;

import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 任务工具类
 *
 * @author <a href="https://www.lvfeiy.top">吕飞扬</a>
 * @date 2024/4/19 13:07
 */
@Slf4j
@SuppressWarnings("unchecked")
public class TaskUtil {
    /**
     *  所有实现了Job接口的类
     */
    private static final CopyOnWriteArraySet<String> JOB_CLASS_CACHE = new CopyOnWriteArraySet<String>();

    /**
     * 创建任务
     *
     * @param job       任务
     * @param scheduler 调度器
     */
    public static void createTask(JobDTO job, Scheduler scheduler) {
        if (Objects.isNull(job) || Objects.isNull(scheduler)) {
            log.error("TaskUtil create task error,job or scheduler is null");
            return;
        }
        String clazz = job.getJobClass();
        Class<? extends org.quartz.Job> jobClass = null;
        try {
            jobClass = (Class<? extends org.quartz.Job>) Class.forName(clazz);
        } catch (ClassNotFoundException e) {
            log.error("TaskUtil task class not found:{}", job);
            return;
        }
        JobDetail jobDetail = JobBuilder.newJob(jobClass).storeDurably().withIdentity(job.getJobName().trim(), job.getJobGroup().trim())
                //任务共享初始化
                .usingJobData("count", 1)
                .build();
        TriggerBuilder<Trigger> triggerTriggerBuilder = TriggerBuilder.newTrigger()
                .withIdentity(job.getJobName().concat("_trigger"), job.getJobGroup().concat("_trigger"));

        if (!StringUtils.isBlank(job.getCronExpression())) {
            triggerTriggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression().trim()));
        } else {
            triggerTriggerBuilder.startNow();
        }
        Trigger trigger = triggerTriggerBuilder.build();
        try {

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            log.error("TaskUtil create task error", e);
        }
    }

    /**
     * 暂停任务
     *
     * @param scheduler 调度器
     * @param jobName   任务名称
     */
    public static void pauseTask(Scheduler scheduler, String jobName) {
        if (Objects.isNull(scheduler) || Objects.isNull(jobName)) {
            log.error("TaskUtil pause task error,scheduler or jobName is null");
            return;
        }
        try {
            scheduler.pauseJob(JobKey.jobKey(jobName.trim()));
        } catch (SchedulerException e) {
            log.error("TaskUtil pause task error", e);
        }
    }

    /**
     * 恢复任务
     *
     * @param scheduler 调度器
     * @param jobName   任务名称
     */
    public static void resumeTask(Scheduler scheduler, String jobName) {
        if (Objects.isNull(scheduler) || Objects.isNull(jobName)) {
            log.error("TaskUtil resume task error,scheduler or jobName is null");
            return;
        }
        try {
            scheduler.resumeJob(JobKey.jobKey(jobName.trim()));
        } catch (SchedulerException e) {
            log.error("TaskUtil resume task error", e);
        }
    }

    /**
     * 删除任务
     *
     * @param scheduler 调度器
     * @param jobName   任务名称
     */
    public static void deleteTask(Scheduler scheduler, String jobName) {
        if (Objects.isNull(scheduler) || Objects.isNull(jobName)) {
            log.error("TaskUtil delete task error,scheduler or jobName is null");
            return;
        }
        try {
            scheduler.deleteJob(JobKey.jobKey(jobName.trim()));
        } catch (SchedulerException e) {
            log.error("TaskUtil delete task error", e);
        }
    }

    /**
     * 执行一次任务
     *
     * @param scheduler 调度器
     * @param jobName   任务名称
     */

    public static void runTaskOnce(Scheduler scheduler, String jobName) {
        if (Objects.isNull(scheduler) || Objects.isNull(jobName)) {
            log.error("TaskUtil run task once error,scheduler or jobName is null");
            return;
        }
        try {
            scheduler.triggerJob(JobKey.jobKey(jobName.trim()));
        } catch (SchedulerException e) {
            log.error("TaskUtil run task once error", e);
        }
    }

    /**
     * 修改任务
     *
     * @param scheduler 调度器
     * @param job       任务
     */

    public static void modifyTask(Scheduler scheduler, JobDTO job) {
        if (Objects.isNull(scheduler) || Objects.isNull(job)) {
            log.error("TaskUtil modify task error,scheduler or job is null");
            return;
        }
        try {
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(TriggerKey.triggerKey(job.getJobName().concat("_trigger"), job.getJobGroup().concat("_trigger")));
            if (Objects.isNull(trigger)) {
                //单次任务
                if (!StringUtils.isBlank(job.getCronExpression())) {
                    //创建触发器关联
                    JobDetail jobDetail = scheduler.getJobDetail(JobKey.jobKey(job.getJobName().trim()));
                    //单次任务需要删除任务重新创建cron任务
                    deleteTask(scheduler, job.getJobName());
                    log.info("modifyTask jobDetail:{}", jobDetail);

                    CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                            .withIdentity(job.getJobName().concat("_trigger"), job.getJobGroup().concat("_trigger"))
                            .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression().trim())).build();
                    scheduler.scheduleJob(jobDetail, cronTrigger);
                }
            } else {
                //cron任务
                if (!StringUtils.isBlank(job.getCronExpression())) {
                    //cron表达式修改
                    CronTrigger newTrigger = trigger.getTriggerBuilder().withIdentity(job.getJobName().concat("_trigger"), job.getJobGroup().concat("_trigger"))
                            //withMisfireHandlingInstructionDoNothing防止修改之后之前的任务立即执行
                            .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression().trim()).withMisfireHandlingInstructionDoNothing()).build();

                    scheduler.rescheduleJob(TriggerKey.triggerKey(job.getJobName().concat("_trigger"), job.getJobGroup().concat("_trigger")), newTrigger);
                } else {
                    //从cron任务变成单次任务
                    scheduler.unscheduleJob(TriggerKey.triggerKey(job.getJobName().concat("_trigger"), job.getJobGroup().concat("_trigger")));
                }
            }
        } catch (SchedulerException e) {
            log.error("TaskUtil modify task error", e);
        }
    }

    public static Set<String> getClassInCache() {
        return JOB_CLASS_CACHE;
    }

    public static void addClassInCache(String... jobClass) {
        JOB_CLASS_CACHE.addAll(Arrays.asList(jobClass));

    }

    public static void addClassInCache(Set<String> jobClass) {
        JOB_CLASS_CACHE.addAll(jobClass);
    }

    public static void removeClassInCache(String jobClass) {
        JOB_CLASS_CACHE.remove(jobClass);
    }

}
